package com.intretech.umsin.common.web;

import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @version V1.0
 * @ClassName: ApiResult
 * @Description: ApiResult 用于格式化输出接口请求返回信息 , 成功表示为"0000" 其余为失败;message属性字段用于传递额外信息至前台（通常为错误信息）
 * @author: 李启联
 * @date: 2022-04-15 14:36
 * @Copyright: Copyright (c) 2022
 */
public class ApiResult<T> {

    public final static String COD_SUCCEED = "0000";
    public final static String COD_FAILED = "9999";
    private final static String MSG_SUCCEED = "ok";
    private final static ApiResult<Void> SUCCESS = new ApiResult<>();// 简单的成功响应对象.

    private final String code;
    private final String message;
    private  T data;

    public String getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public ApiResult() {
        this(COD_SUCCEED, MSG_SUCCEED);
    }

    public ApiResult(String code, String message) {
        this(code, message, null);
    }

    public ApiResult(String code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /**
     * 判断当前响应数据是否为成功应答.
     *
     * @return true-当前请求为成功响应；false-失败.
     */
    public boolean isSuccessfully() {
        return COD_SUCCEED.equals(getCode());
    }

    /**
     * 简单的成功应答对象.
     *
     * @return 返回不带数据的响应结果
     */
    public static ApiResult<Void> succeedResponse() {
        return SUCCESS;
    }

    /**
     * 包含指定响应数据的应答对象.
     *
     * @param data 响应实际数据
     * @param <T>  数据类型
     * @return 返回响应结果对象.
     */
    public static <T> ApiResult<T> succeedResponse(T data) {
        return new ApiResult<>(COD_SUCCEED, MSG_SUCCEED, data);
    }

    /**
     * 包含指定响应数据的应答对象.
     * @param message 响应提醒信息
     * @param data 响应实际数据
     * @param <T> 数据类型
     * @return
     */
    public static <T> ApiResult<T> succeedResponse(String message,T data) {
        return new ApiResult<>(COD_SUCCEED, message, data);
    }


    /**
     * 简单的失败应答对象.
     * @return
     */
    public static ApiResult<Void> failedResponse() {
        return new ApiResult<>(COD_FAILED, "fail");
    }


    /**
     * 返回失败响应应答对象.
     * @param message 失败消息
     * @param data  数据
     * @param <T> 数据类型
     * @return
     */
    public static <T> ApiResult<T> failedResponse(String message,T data) {
        return new ApiResult<>(COD_FAILED, message, data);
    }

    /**
     * 返回失败响应应答对象.
     * @param code 响应码
     * @param message 失败消息
     * @return
     * @param <T>
     */
    public static <T> ApiResult<T> failedResponse(String code,String message) {
        return new ApiResult<>(code, message, null);
    }

    /**
     * 返回失败响应应答对象.
     * @param message 失败消息
     * @param <T>
     * @return
     */
    public static <T> ApiResult<T> failedResponse(String message) {
        return new ApiResult<>(COD_FAILED, message, null);
    }


    /**
     * 调用目标动作，并在成功执行完成后，返回调用结果（于data中）.
     *
     * @param action 请求后台执行的动作函数
     * @param p      请求后台过程中使用的参数
     * @param <T>    参数类型
     * @param <R>    返回值类型
     * @return 响应结果信息.
     */
    public static <T, R> ApiResult<R> responseFor(Function<T, R> action, T p) {
        try {
            R data = action.apply(p);
            return new ApiResult<>(COD_SUCCEED, MSG_SUCCEED, data);
        } catch (Exception e) {
            return failedResponse(e.getMessage());
        }
    }

    /**
     * 调用目标动作(含两个入参)，并在成功执行完成后，返回调用结果（于data中）.
     *
     * @param action 请求后台执行的动作函数
     * @param p1     请求后台过程中使用的参数1
     * @param p2     请求后台过程中使用的参数2
     * @param <T>    参数1类型
     * @param <U>    参数2类型
     * @param <R>    返回值类型
     * @return 响应结果信息.
     */
    public static <T, U, R> ApiResult<R> responseFor(BiFunction<T, U, R> action, T p1, U p2) {
        try {
            R data = action.apply(p1, p2);
            return new ApiResult<>(COD_SUCCEED, MSG_SUCCEED, data);
        } catch (Exception e) {
            return failedResponse(e.getMessage());
        }
    }

    /**
     * 调用目标动作，在成功后返回要给成功执行标志.
     *
     * @param action 请求后台执行的动作函数
     * @param p      请求后台过程中使用的参数
     * @param <T>    参数类型
     * @return 响应结果信息.
     */
    public static <T> ApiResult<Void> responseFor(Consumer<T> action, T p) {
        try {
            action.accept(p);
            return SUCCESS;
        } catch (Exception e) {
            return failedResponse(e.getMessage());
        }
    }

    /**
     * 调用目标动作，在成功后返回要给成功执行标志.
     *
     * @param action 请求后台执行的动作函数
     * @param <R>    参数类型
     * @return 响应结果信息.
     */
    public static <R> ApiResult<R> responseFor(Supplier<R> action) {
        try {
            R data = action.get();
            return new ApiResult<>(COD_SUCCEED, MSG_SUCCEED, data);
        } catch (Exception e) {
            return failedResponse(e.getMessage());
        }
    }


}
